
use crate::base::{get_ch_pool,Table};

pub struct IncrJoinTable<'a>{
    tconf: &'a Table,
    table_name: String,
    pk_col: &'a str,
}
impl <'a> IncrJoinTable<'a> {
    pub fn new(tconf: &'a Table)->Option<Self>{
        let table_name=format!("tmp_{}_INCR_JOIN",tconf.file_name);
        if let Some((pk_col,_))=tconf.db_calc_cols.iter().find(|(_,v)|v.as_str()=="#INCR"){
            Some(IncrJoinTable{
                tconf,table_name,pk_col
            })
        }else{
            None
        }
    }
    pub fn get_name(&self)->&str{
        &self.table_name
    }
    pub async fn create(&self,where_cause:Option<&str>)->anyhow::Result<()>{
        let sql=format!(r#"CREATE TABLE IF NOT EXISTS {} (UKEY String,ID UInt64)
                        ENGINE = Join(ANY,LEFT,UKEY)"#,self.table_name);
        let mut client=get_ch_pool().get_handle().await?;
        client.execute(sql).await?;
        let sql =format!("truncate table {}",self.table_name);
        client.execute(&sql).await?;
        let ukeys=if self.tconf.unique_keys.len()==1 {
            self.tconf.unique_keys[0].clone()
        }else{
            format!("concat({})",self.tconf.unique_keys.join(","))
        };
        let where_cause=if let Some(wc)=where_cause{
            format!("where {wc}")
        }else{
            "".to_owned()
        };
        let sql=format!("insert into {}(UKEY,ID) select {ukeys},{} from {} {where_cause}",self.table_name,self.pk_col,self.tconf.table_name);
        client.execute(sql).await?;
        Ok(())
    }
    pub async fn insert_new(&self)->anyhow::Result<()>{
        let mut client=get_ch_pool().get_handle().await?;
        let ukeys=if self.tconf.unique_keys.len()==1 {
            self.tconf.unique_keys[0].clone()
        }else{
            format!("concat({})",self.tconf.unique_keys.join(","))
        };
        let tmp_table_name=format!("tmp_{}",self.tconf.file_name);
        let tname=self.table_name.as_str();
        let with_exp=format!("WITH joinGet('{tname}','ID',{ukeys}) as ID,(select max(ID) from {tname}) as MAXID");
        let new_id = format!("row_number() over(order by {ukeys})+MAXID");
        let sql = format!(
            "{with_exp} insert into {tname}(UKEY,ID) select {ukeys},{new_id} from {tmp_table_name} where ID=0",
        );
        client.execute(sql).await?;
        Ok(())
    }
    pub async fn drop(&self)->anyhow::Result<()>{
        let sql=format!("drop table if exists {}",self.table_name);
        let mut client=get_ch_pool().get_handle().await?;
        client.execute(sql).await?;
        Ok(())
    }

}